package vn.fpt.fsoft.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import vn.fpt.fsoft.common.exception.MyException;
import vn.fpt.fsoft.dao.IBaseDao;

/**
 * @author DuongPV1
 * This is class BaseDao contains method common of class Dao
 * Class have type generic include:
 * 		T is type entity
 * 		
 * 		K is type of key to find entity
 * Include methods:
 * 		T get(K key)
 * 		List<T> getAll();
 * 		boolean insert(T entity)
 * 		boolean update(T entity)
 * 		boolean delete(K key)
 * */
public class BaseDaoImpl<T, K extends Serializable> implements
		IBaseDao<T, K> {
	@Autowired
	SessionFactory sessionFactory;

	private Session session;
	private Class<T> entityClass;
	@SuppressWarnings("unchecked")
	public BaseDaoImpl() {
		 ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
	        this.entityClass = (Class<T>) genericSuperclass.getActualTypeArguments()[0];
	}
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}

	public String getTableName() {
		return this.entityClass.getSimpleName();
	}

	public Session getSession() {
		return sessionFactory.getCurrentSession();
	}

	/**
	 * @Return List<T> , list of all entity
	 * */
	@Transactional
	public List<T> getAll() throws MyException {
		session = sessionFactory.openSession();
		String hsql = "from " + this.getTableName(); 
		Query query = session.createQuery(hsql);
		return (List<T>) query.list();
	}

	@Override
	public T get(K key) {
		session = sessionFactory.openSession();
		T entity = (T) session.get(entityClass, key);
		return entity;
	}

	@Override
	public boolean insert(T entity) throws MyException {
		session = sessionFactory.openSession();
		boolean result = false;
		try {
			session.save(entity);
			result = true;
		} catch (Exception me) {
			throw new MyException("Exception Hibernate");

		}
		return result;
	}

	@Override
	public boolean update(T entity) throws MyException {
		session = sessionFactory.openSession();
		boolean result = false;
		try {
			session.update(entity);
			result = true;
		} catch (Exception me) {
			throw new MyException("Exception Hibernate");

		}
		return result;
	}

	@Override
	public boolean delete(K key) throws MyException {
		session = sessionFactory.openSession();
		boolean result = false;
		try {
			T entity = (T) session.get(entityClass, key);
			if (entity == null) {
				result = false;
			} else {
				session.delete(entity);
				result = true;
			}
		} catch (Exception me) {
			throw new MyException("Exception Hibernate");
		}
		return result;
	}

}
